package com.laiketui.plugin.common.service.order;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.laiketui.core.cache.RedisUtil;
import com.laiketui.core.common.SplitUtils;
import com.laiketui.core.exception.LaiKeAPIException;
import com.laiketui.core.lktconst.GloabConst;
import com.laiketui.core.utils.okhttp.HttpUtils;
import com.laiketui.plugin.common.domain.MainVo;
import com.laiketui.plugin.common.domain.base.ExpressModel;
import com.laiketui.plugin.common.domain.base.OrderModel;
import com.laiketui.plugin.common.domain.base.User;
import com.laiketui.plugin.common.domain.base.order.ExpressDeliveryModel;
import com.laiketui.plugin.common.domain.lktconst.DictionaryConst;
import com.laiketui.plugin.common.domain.lktconst.ErrorCode;
import com.laiketui.plugin.common.interfaces.PubliceService;
import com.laiketui.plugin.common.interfaces.order.PublicExpressService;
import com.laiketui.plugin.common.mapper.*;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.net.URLDecoder;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 物流公司信息服务接口
 *return
 * @author wangxian
 */
@Service("publicExpressService")
public class PublicExpressServiceImpl implements PublicExpressService {

    private final Logger logger = LoggerFactory.getLogger(PublicExpressServiceImpl.class);

    @Override
    public List<ExpressModel> getExpressInfo() {
        try{
            List<ExpressModel> cacheExpress = (List<ExpressModel>) redisUtil.get(GloabConst.RedisHeaderKey.EXPRESS_ALL);
            if( cacheExpress != null){
                return cacheExpress;
            }
            return expressModelMapper.selectAll();
        }catch (Exception e){
            e.printStackTrace();
            logger.error("获取物流公司信息失败：{}",e.getMessage());
        }

        return null;
    }

    @Override
    public boolean setWxAppUploadShippingInfo(MainVo vo, String sNo) throws LaiKeAPIException {
        try {
            if (StringUtils.isEmpty(sNo)){
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_CSCW, "参数错误", "setWxAppUploadShippingInfo");
            }
            OrderModel orderModel = new OrderModel();
            orderModel.setStore_id(vo.getStoreId());
            orderModel.setsNo(sNo);
            orderModel = orderModelMapper.selectOne(orderModel);
            //获取用户消息
            User user = new User();
            user.setStore_id(vo.getStoreId());
            user.setUser_id(orderModel.getUser_id());
            user = userMapper.selectOne(user);
            //获取微信小程序支付配置
            String paymentJson = paymentConfigModelMapper.getPaymentConfigInfo(vo.getStoreId(), DictionaryConst.OrderPayType.ORDERPAYTYPE_MINI_WECHAT);
            paymentJson = URLDecoder.decode(paymentJson, GloabConst.Chartset.UTF_8);
            logger.info("小程序支付配置信息：" + paymentJson);
            JSONObject payJson = JSONObject.parseObject(paymentJson);
            String mchID = payJson.getString("mch_id");
            logger.info("mchID:{}", mchID);
            String pSno = null;
/*            //是否拆单，拆单使用的是同一个微信订单号 进行分拆发货
            if (StringUtils.isNotEmpty(orderModel.getP_sNo())){
                //判断子订单是否全部发货完成/或者未发货的在售后中
                OrderModel sonOrderModel = new OrderModel();
                sonOrderModel.setStore_id(vo.getStoreId());
                sonOrderModel.setP_sNo(orderModel.getP_sNo());
                List<OrderModel> sonOrderModelList = orderModelMapper.select(sonOrderModel);
                for (OrderModel model : sonOrderModelList) {
                    //未发货 没有售后完成
                    if (model.getStatus() <= DictionaryConst.OrdersStatus.ORDERS_R_STATUS_CONSIGNMENT
                            && model.getStatus() != DictionaryConst.OrdersStatus.ORDERS_R_STATUS_CLOSE ){
                        //判断子订单是否正在售后中
                        if (returnOrderModelMapper.orderReturnIsNotEndOrEnd(vo.getStoreId(), model.getsNo()) <= 0){
                            return true;
                        }
                    }
                }
                pSno = orderModel.getP_sNo();
            }*/
            //修改订单的微信订单状态为以发货
            orderModelMapper.UpdateWxOrderStatusByRealSno(vo.getStoreId(), orderModel.getReal_sno(), 2);
            HashMap<String, Object> map = new HashMap<>();
            map.put("store_id", vo.getStoreId());
            map.put("sNo", sNo);
            List<Map<String, Object>> orderDetailBypSnoOrsNo = orderDetailsModelMapper.getOrderDetailBypSnoOrsNo(map);
            //获取微信token
            String accessToken = publiceService.getWeiXinToken(vo.getStoreId());
            String url = String.format(GloabConst.WeiXinUrl.UPLOAD_SHIPPING_INFO, accessToken);
            HashMap<String, Object> parmaMap = new HashMap<>();
            Map<String, Object> resultMapTemp;
            //获取全部物流信息
            List<Object> resultList = new ArrayList<>(16);
            HashMap<String, Object> order_key = new HashMap<>();
            //订单单号类型，用于确认需要上传详情的订单。枚举值1，使用下单商户号和商户侧单号；枚举值2，使用微信支付单号
            order_key.put("order_number_type", 1);
            //mchid:支付下单商户的商户号，由微信支付生成并下发。
            //out_trade_no 商户系统内部订单号，只能是数字、大小写字母`_-*`且在同一个商户号下唯一
            order_key.put("mchid", mchID);
            order_key.put("out_trade_no", orderModel.getReal_sno());
//            order_key.put("transaction_id", "4200002225202405178855537598");
            parmaMap.put("order_key", order_key);
            //logistics_type:物流模式，发货方式枚举值：1、实体物流配送采用快递公司进行实体物流配送形式 2、同城配送 3、虚拟商品，虚拟商品，例如话费充值，点卡等，无实体配送形式 4、用户自提
            //线下自提
            if (orderModel.getSelf_lifting().equals(OrderModel.SELF_LIFTING_PICKED_UP)){
                parmaMap.put("logistics_type", 4);
                parmaMap.put("delivery_mode", "UNIFIED_DELIVERY");
                resultMapTemp = new HashMap<>(16);
                StringBuilder goodsListTemp = new StringBuilder();
                for (Map<String, Object> orderDetails : orderDetailBypSnoOrsNo) {
                    goodsListTemp.append(MapUtils.getString(orderDetails, "p_name")).append("*").append(MapUtils.getInteger(orderDetails, "num")).append(",");
                }
                resultMapTemp.put("item_desc", goodsListTemp);
                resultList.add(resultMapTemp);
            }else {
                parmaMap.put("logistics_type", 1);
                ExpressDeliveryModel expressDeliveryModel = null;
                //物流去重,如果多个商品统一发货则只显示一个物流动态
                Set<String> wuLiuIds = new HashSet<>();
                //商品信息快递单号分组
                Map<String, Map<String, Object>> goodsGroupMap = new HashMap<>(16);
                //商品分组
                Map<String, StringBuilder> goodsGroupList = new HashMap<>(16);
                for (Map<String, Object> orderDetails : orderDetailBypSnoOrsNo) {
                    String courier_num = MapUtils.getString(orderDetails, "courier_num");
                    String express_id = MapUtils.getString(orderDetails, "express_id");
                    Integer id = MapUtils.getInteger(orderDetails, "id");
                    String p_name = MapUtils.getString(orderDetails, "p_name");
                    Integer num = MapUtils.getInteger(orderDetails, "num");
                    resultMapTemp = new HashMap<>(16);
                    if (courier_num == null || express_id == null){
                        continue;
                    }
                    //快递公司id
                    List<String> expressIds =  Arrays.asList(express_id.split(","));
                    //快递单号
                    List<String> courierNums = Arrays.asList(courier_num.split(","));
                    for (int i = 0; i < expressIds.size(); i++) {
                        String goods = "";
                        resultMapTemp = new HashMap<>();
                        String expressId = expressIds.get(i);
                        String courierNum = courierNums.get(i);
                        if (StringUtils.isEmpty(courierNum)) {
                            //剔除没有物流单号的商品
                            continue;
                        }
                        //快递公司代号
                        String kdCode = "";
                        String wuLiuKey = expressId + courierNum;
                        //查询发货记录
                        expressDeliveryModel = new ExpressDeliveryModel();
                        expressDeliveryModel.setOrderDetailsId(id);
                        expressDeliveryModel.setCourierNum(courierNum);
                        expressDeliveryModel.setExpressId(Integer.valueOf(expressId));
                        expressDeliveryModel = expressDeliveryModelMapper.selectOne(expressDeliveryModel);

                        //获取商品信息
                        goods = p_name + "*" + expressDeliveryModel.getNum() + ",";
                        if (wuLiuIds.contains(wuLiuKey)) {
                            //获取同单物流信息
                            resultMapTemp = goodsGroupMap.get(courierNum);
                            StringBuilder goodsListTemp = goodsGroupList.get(courierNum);
                            goodsListTemp.append(goods);
                            resultMapTemp.put("item_desc", goodsListTemp);
                            continue;
                        }
                        //分组
                        if (goodsGroupMap.containsKey(courierNum)) {
                            //获取同单物流信息
                            resultMapTemp = goodsGroupMap.get(courierNum);
                            StringBuilder goodsListTemp = goodsGroupList.get(courierNum);
                            resultMapTemp.put("item_desc", goodsListTemp);
                        } else {
                            //商品信息根据物流单分组
                            StringBuilder goodsListTemp = new StringBuilder();
                            if (goodsGroupList.containsKey(courierNum)) {
                                goodsListTemp.append(goodsGroupList.get(courierNum));
                            } else {
                                goodsListTemp.append(goods);
                                goodsGroupList.put(courierNum, goodsListTemp);
                            }
                            ExpressModel expressModel = expressModelMapper.selectByPrimaryKey(expressId);
                            //构造数据结构
                            //商品信息，例如：微信红包抱枕*1个，限120个字以内
                            resultMapTemp.put("item_desc", goodsListTemp);
                            //物流单号，物流快递发货时必填，示例值: 323244567777 字符字节限制: [1, 128]
                            resultMapTemp.put("tracking_no", courierNum);
                            //物流公司编码，快递公司ID，参见「查询物流公司编码列表」，物流快递发货时必填， 示例值: DHL 字符字节限制: [1, 128]
                            resultMapTemp.put("express_company", expressModel.getWx_delivery_id());
                            HashMap<String, Object> contact = new HashMap<>();
                            if (orderModel.getMobile() != null){
                                //receiver_contact:收件人联系方式，收件人联系方式为，采用掩码传输，最后4位数字不能打掩码 示例值: `189****1234, 021-****1234, ****1234, 0**2-***1234, 0**2-******23-10, ****123-8008` 值限制: 0 ≤ value ≤ 1024
                                contact.put("receiver_contact", orderModel.getMobile().replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
                            }else {
                                //寄件人联系方式，寄件人联系方式，采用掩码传输，最后4位数字不能打掩码 示例值: `189****1234, 021-****1234, ****1234, 0**2-***1234, 0**2-******23-10, ****123-8008` 值限制: 0 ≤ value ≤ 1024
                                // 店铺ID
                                String mchId = com.laiketui.plugin.common.tool.str.StringUtils.trim(orderModel.getMch_id(), SplitUtils.DH);
                                String tel = mchModelMapper.selectByPrimaryKey(mchId).getTel();
                                if (tel != null){
                                    contact.put("consignor_contact", tel.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
                                }else {
                                    contact.put("consignor_contact", "156****1234");
                                }
                            }
                            //联系方式，当发货的物流公司为顺丰时，联系方式为必填，收件人或寄件人联系方式二选一
                            resultMapTemp.put("contact", contact);
                            goodsGroupMap.put(courierNum, resultMapTemp);
                        }
                        wuLiuIds.add(wuLiuKey);
                        resultList.add(resultMapTemp);
                    }
                }
                //delivery_mode:发货模式，发货模式枚举值：1、UNIFIED_DELIVERY（统一发货）2、SPLIT_DELIVERY（分拆发货） 示例值: UNIFIED_DELIVERY
                //is_all_delivered:分拆发货模式时必填，用于标识分拆发货模式下是否已全部发货完成，只有全部发货完成的情况下才会向用户推送发货完成通知。示例值: true/false
                if (resultList.size() <= 1){
                    //一个发货记录  UNIFIED_DELIVERY（统一发货）
                    parmaMap.put("delivery_mode", "UNIFIED_DELIVERY");
                }else {
                    //多个发货记录  SPLIT_DELIVERY（分拆发货）
                    parmaMap.put("delivery_mode", "SPLIT_DELIVERY");
                    parmaMap.put("is_all_delivered", true);
                }
            }
            //	shipping_list : 物流信息列表，发货物流单列表，支持统一发货（单个物流单）和分拆发货（多个物流单）两种模式，多重性: [1, 10]
            if (resultList.size() > 10){
                resultList = resultList.subList(0, 10);
            }
            parmaMap.put("shipping_list", resultList);
            //	upload_time	string上传时间，用于标识请求的先后顺序 示例值: `2022-12-15T13:29:35.120+08:00` RFC 3339格式时间
            // 获取当前时间的ZonedDateTime实例
            ZonedDateTime now = ZonedDateTime.now();
            // 使用DateTimeFormatter格式化为RFC 3339格式
            DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
            String rfc3339Time = now.format(formatter);
            parmaMap.put("upload_time", rfc3339Time);
            //payer	支付者，支付者信息
            HashMap<String, Object> payer = new HashMap<>();
            //用户标识，用户在小程序appid下的唯一标识。 下单前需获取到用户的Openid 示例值: oUpF8uMuAJO_M2pxb1Q9zNjWeS6o 字符字节限制: [1, 128]
            payer.put("openid", user.getWx_id());
            parmaMap.put("payer", payer);
            logger.info("发货信息录入接口:{}", JSON.toJSONString(parmaMap));
            String resultJson = HttpUtils.post(url, JSON.toJSONString(parmaMap));
            Map<String, Object> parma = JSON.parseObject(resultJson, new TypeReference<Map<String, Object>>() {
            });
            if (!MapUtils.getString(parma, "errmsg").equals("ok")){
                logger.error("发货信息录入接口微信返回错误:" + resultJson);
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "setWxAppUploadShippingInfo");
            }
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            logger.error("发货信息录入接口 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "setWxAppUploadShippingInfo");
        }
        return true;
    }

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private ExpressModelMapper expressModelMapper;

    @Autowired
    private PaymentConfigModelMapper paymentConfigModelMapper;

    @Autowired
    private CustomerModelMapper customerModelMapper;

    @Autowired
    private ReturnOrderModelMapper returnOrderModelMapper;

    @Autowired
    private MchModelMapper mchModelMapper;

    @Autowired
    private ExpressDeliveryModelMapper expressDeliveryModelMapper;

    @Autowired
    private OrderModelMapper orderModelMapper;

    @Autowired
    private PubliceService publiceService;

    @Autowired
    private OrderDetailsModelMapper orderDetailsModelMapper;

    @Autowired
    private UserMapper userMapper;

}

